package com.haltakov.letterjumble.ui;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.BorderFactory;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.filechooser.FileNameExtensionFilter;

import com.haltakov.letterjumble.Messages;
import com.haltakov.letterjumble.game.api.GameController;
import com.haltakov.letterjumble.game.api.GameException;
import com.haltakov.letterjumble.game.api.Player;
import com.haltakov.letterjumble.game.api.PlayerType;
import com.haltakov.letterjumble.ui.components.GameBoard;
import com.haltakov.letterjumble.ui.components.GameButtons;
import com.haltakov.letterjumble.ui.components.PlayerLetters;
import com.haltakov.letterjumble.ui.components.PlayersInfo;

import static com.haltakov.letterjumble.ui.LookAndFeel.*;

@SuppressWarnings("serial")
public class MainFrame extends JFrame {
	
	// main GUI components
	
	private JPanel backPanel;
	private GameBoard boardComponent; 
	private PlayerLetters playerLettersPanel;
	private PlayersInfo playersInfoPanel;
	private GameButtons gameButtonsPanel;
	
	// the main controller
	private GameController game;
	
	private final JFileChooser fileChooser;

	private void createMenu() {
		
		JMenuBar menu = new JMenuBar();
		setJMenuBar(menu);

		JMenu gameMenu = new JMenu(Messages.getString("MainFrame.game")); 
		menu.add(gameMenu);

		JMenuItem newGameItem = new JMenuItem(Messages.getString("MainFrame.newgame"));
		gameMenu.add(newGameItem);

		newGameItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				NewGameDialog dialog = new NewGameDialog(game);
				dialog.setVisible(true);
			}
		});

		JMenuItem saveGameItem = new JMenuItem(Messages.getString("MainFrame.save")); //$NON-NLS-1$
		gameMenu.add(saveGameItem);

		JMenuItem loadGameItem = new JMenuItem(Messages.getString("MainFrame.load")); //$NON-NLS-1$
		gameMenu.add(loadGameItem);

		JMenuItem exitGameItem = new JMenuItem(Messages.getString("MainFrame.exit")); //$NON-NLS-1$
		gameMenu.add(exitGameItem);

		JMenu settingsMenu = new JMenu(Messages.getString("MainFrame.settings")); //$NON-NLS-1$
		menu.add(settingsMenu);

		JMenuItem settingsItem = new JMenuItem(Messages.getString("MainFrame.mainsettings")); //$NON-NLS-1$
		settingsMenu.add(settingsItem);

		settingsItem.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				SettingsDialog dialog = new SettingsDialog(game);
				dialog.setVisible(true);
			}
		});

		JMenuItem dictionaryItem = new JMenuItem(Messages.getString("MainFrame.dictionary")); //$NON-NLS-1$
		settingsMenu.add(dictionaryItem);

		dictionaryItem.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				DictionaryDialog dialog = new DictionaryDialog(game.getDictionary());
				dialog.setVisible(true);
			}
		});
		
		saveGameItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (fileChooser.showSaveDialog(MainFrame.this) == JFileChooser.APPROVE_OPTION) {
					try {
						game.saveGame(fileChooser.getSelectedFile());
						
						game.showMessage(Messages.getString("MainFrame.successsaved")); //$NON-NLS-1$
					} catch (GameException e1) {
						game.showError(e1);
					}
				}
			}
		});
		
		loadGameItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				if (fileChooser.showOpenDialog(MainFrame.this) == JFileChooser.APPROVE_OPTION) {
					try {
						game.loadGame(fileChooser.getSelectedFile());
						
						game.showMessage(Messages.getString("MainFrame.successloaded")); //$NON-NLS-1$
					} catch (GameException e1) {
						game.showError(e1);
					}
				}
			}
		});

		JMenu helpMenu = new JMenu(Messages.getString("MainFrame.help")); //$NON-NLS-1$
		menu.add(helpMenu);

		JMenuItem aboutItem = new JMenuItem(Messages.getString("MainFrame.aboutgame")); //$NON-NLS-1$
		helpMenu.add(aboutItem);
	}

	private void createBackgroud() {
		Image tmpBack = null;
		try {
			tmpBack = ImageIO.read(new File(game.getDataDirectory() + "back.png")); //$NON-NLS-1$
		} catch (IOException e) {}

		final Image back = tmpBack;

		backPanel = new JPanel(new BorderLayout()) {
			@Override
			public void paintComponent(Graphics g) {
				Dimension d = getSize();

				if (back == null) {
					g.setColor(PANEL_BACKGROUND_COLOR);
					g.fillRect(0, 0, d.width, d.height);
				}
				else {
					int w = back.getWidth(null);
					int h = back.getHeight(null);

					for (int i = 0; i<d.width; i += w) {
						for (int j = 0; j<d.height; j += h) {
							g.drawImage(back, i, j, null);
						}
					}
				}

				super.paintComponent(g);
			}
		};

		backPanel.setPreferredSize(new Dimension(1100, 750));
		backPanel.setOpaque(false);

		getContentPane().add(backPanel);
	}

	private JPanel createFunctionalPanel() {
		JPanel funcPanel = new JPanel(new FlowLayout());

		funcPanel.setOpaque(false);
		funcPanel.setPreferredSize(new Dimension(350, 750));

		// PLAYERS INFO
		JPanel piContainer = new JPanel();
		piContainer.setBorder(BorderFactory.createLineBorder(PANEL_BORDER_COLOR, 5));
		piContainer.setBackground(PANEL_BACKGROUND_COLOR);

		playersInfoPanel = new PlayersInfo();
		playersInfoPanel.setPreferredSize(new Dimension(300, 400));
		playersInfoPanel.setOpaque(false);

		piContainer.add(playersInfoPanel);
		funcPanel.add(piContainer);

		

		// PLAYER LETTERS
		JPanel plContainer = new JPanel();
		plContainer.setBorder(BorderFactory.createLineBorder(PANEL_BORDER_COLOR, 5));
		plContainer.setBackground(PANEL_BACKGROUND_COLOR);

		playerLettersPanel = new PlayerLetters();
		playerLettersPanel.setPreferredSize(new Dimension(300, 100));
		playerLettersPanel.setBackground(PANEL_BACKGROUND_COLOR);
		playerLettersPanel.setMaximumSize(new Dimension(300, 100));

		plContainer.add(playerLettersPanel);
		funcPanel.add(plContainer);



		// GAME BUTTONS
		JPanel gbContainer = new JPanel();
		gbContainer.setBorder(BorderFactory.createLineBorder(PANEL_BORDER_COLOR, 5));
		gbContainer.setBackground(PANEL_BACKGROUND_COLOR);

		gameButtonsPanel = new GameButtons(game);
		gameButtonsPanel.setPreferredSize(new Dimension(300, 120));
		gameButtonsPanel.setBackground(PANEL_BACKGROUND_COLOR);

		gbContainer.add(gameButtonsPanel);
		funcPanel.add(gbContainer);
		
		return funcPanel;
	}

	public void setPlayer(int id, Player player) {
		playersInfoPanel.setPlayer(id, player);
	}

	public void updatePlayer(int id) {
		playersInfoPanel.updatePlayer(id);
	}

	public MainFrame(GameController game) {
		
		this.game = game;

		setTitle("Letter Jumble");

		Image logo = null;
		try {
			logo = ImageIO.read(new File(game.getDataDirectory() + "logo.png"));
		} catch (IOException e) {}
		
		
		fileChooser = new JFileChooser(game.getDataDirectory());
		fileChooser.setFileFilter(new FileNameExtensionFilter("XML File", "xml"));
		
		JPanel funcPanel = createFunctionalPanel();

		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setPreferredSize(new Dimension(1100, 780));
		setLayout(new BorderLayout());

		createMenu();
		createBackgroud();

		boardComponent = new GameBoard(game.getBoard(), logo, playerLettersPanel, game);
		backPanel.add(boardComponent, BorderLayout.CENTER);
		backPanel.add(funcPanel, BorderLayout.EAST);	

		pack();
	}
	
	@Override
	public void repaint() {
		super.repaint();
		
		for (Component c: getComponents()) {
			c.repaint();
		}
	}

	public void changePlayer(Player newPlayer, Player oldPlayer) {
		if (newPlayer.getType() == PlayerType.HUMAN)
			playerLettersPanel.changePlayer(newPlayer);		
		
		playersInfoPanel.updatePlayer(game.getPlayers().indexOf(oldPlayer));
		playersInfoPanel.setCurrentPlayer(game.getPlayers().indexOf(newPlayer));
	}

	public void showButtons() {
		gameButtonsPanel.enableAll();		
	}

}
